技巧48 你在容器里吗
在创建容器时,通常会把运行逻辑放到一个shell脚本里,很少会尝试直接在Dockerfile里编写脚本。又或者,你可能在容器运行时用到了各种脚本。无论哪种方式,这些执行的任务通常都需要经过仔细定制,以便能够运行在容器里,并且运行在一台“常规”机器上可能会搞破坏。在这种情况下,设置一些安全防护,防止在容器外部意外执行是很有用的。
问题
用户代码需要知道是否是在一个Docker容器里操作。
解决方案
检查/.dockerenv文件是否存在。如果存在,那么很可能在一个Docker容器里。
注意,这并不是100%确定的——如果任何人或任何事物把/.dockerenv文件删掉,这个检查就会给出误导性的结果。这些情况不太可能发生,但是最坏的情况便是用户得到错误的诊断结果而没有不良影响。用户会认为自己不在Docker容器里,并且在最坏的情况下 不会 运行潜在的破坏性代码。
一个更现实的情况是,在较新的Docker版本里(或者使用的是实现这一行为之前的版本)已经更改或删除了这种未记录的Docker行为。
这些代码可能是启动bash脚本的一部分,如代码清单6-3所示,其后是剩余的启动脚本代码。
代码清单6-3 如果在容器外运行,如下shell脚本会运行失败
#!/bin/bash
if ! [ -f /.dockerenv ]
then
echo 'Not in a Docker container, exiting.'
exit 1
fi
当然,如有需要,可以使用相反的逻辑来确认自己 是不是 运行在容器外面,如代码清单6-4所示。
代码清单6-4 如果在容器里运行,如下shell脚本会运行失败
#!/bin/bash
if [ -f /.dockerenv ]
then
echo 'In a Docker container, exiting.'
exit 1
fi
上述示例使用bash命令来确认文件是否存在,但是绝大多数编程语言有自己的办法来确认容器(或宿主机)文件系统里是否存在某些文件。
讨论
用户可能想知道这种情况多久出现一次。作为一个时常讨论的话题,它经常出现在Docker论坛里,关于这是否是一个有效的用例,又或者是应用程序设计方面存在其他问题,这块仍然存在争议。
撇开这些争议不提,用户很容易陷入需要根据自己是否在Docker容器里来切换代码路径的情况。我们经历过的一个这样的例子便是使用Makefile来构建一个容器。